﻿using System;

namespace FirstFloor.Documents.Pdf
{
    /// <summary>
    /// Uniquely identifies an indirect object in a PDF document.
    /// </summary>
    internal struct ObjectIdentifier
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ObjectIdentifier"/> struct.
        /// </summary>
        /// <param name="number">The number.</param>
        /// <param name="generation">The generation.</param>
        public ObjectIdentifier(int number, int generation)
            : this()
        {
            this.Number = number;
            this.Generation = generation;
        }

        /// <summary>
        /// Gets the number.
        /// </summary>
        /// <value>The number.</value>
        public int Number { get; private set; }
        /// <summary>
        /// Gets the generation.
        /// </summary>
        /// <value>The generation.</value>
        public int Generation { get; private set; }

        /// <summary>
        /// Indicates whether this instance and a specified object are equal.
        /// </summary>
        /// <param name="obj">Another object to compare to.</param>
        /// <returns>
        /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            return ((ObjectIdentifier)obj) == this;
        }

        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer that is the hash code for this instance.
        /// </returns>
        public override int GetHashCode()
        {
            return this.Number ^ this.Generation;
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="o1">The o1.</param>
        /// <param name="o2">The o2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(ObjectIdentifier o1, ObjectIdentifier o2)
        {
            return o1.Number == o2.Number && o1.Generation == o2.Generation;
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="o1">The o1.</param>
        /// <param name="o2">The o2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(ObjectIdentifier o1, ObjectIdentifier o2)
        {
            return !(o1 == o2);
        }

        /// <summary>
        /// Returns the fully qualified type name of this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> containing a fully qualified type name.
        /// </returns>
        public override string ToString()
        {
            return string.Format("{0} {1}", this.Number, this.Generation);
        }
    }
}
